#ifndef _HgeFont_h_
#define _HgeFont_h_

#include "hgeImage.h"
#include "hgeFontGlyph.h"
#include "hgeForwardRef.h"

#include <map>
#include <ft2build.h>
#include FT_FREETYPE_H

/*!
\brief
Implementation of the Font class interface using the FreeType library.

This implementation tries to provide maximal support for any kind of
fonts supported by FreeType. It has been tested on outline font formats
like TTF and PS as well as on bitmap font formats like PCF and FON.

Glyphs are rendered dynamically on demand, so a large font with lots
of glyphs won't slow application startup time.
*/
class hgeFont
{
public:
	hgeFont(const String& font_name, const float point_size,
		const bool anti_aliased, const String& font_filename);

	//! Destructor.
	~hgeFont();

	//! return the point size of the freetype font.
	float getPointSize() const;

	//! return whether the freetype font is rendered anti-aliased.
	bool isAntiAliased() const;

	//! return the point size of the freetype font.
	void setPointSize(const float point_size);

	//! return whether the freetype font is rendered anti-aliased.
	void setAntiAliased(const bool anti_alaised);

	//! Return the string holding the font name.
	const String& getName() const;

	//! Return the type of the font.
	const String& getTypeName() const;

	//Return whether this Font can draw the specified code-point
	bool isCodepointAvailable(utf32 cp) const
	{ return (d_cp_map.find(cp) != d_cp_map.end()); }

	/*!
	\brief
	Draw text into a specified area of the display.

	\param buffer
	GeometryBuffer object where the geometry for the text be queued.

	\param text
	String object containing the text to be drawn.

	\param position
	Reference to a Vector2 object describing the location at which the text
	is to be drawn.

	\param clip_rect
	Rect object describing the clipping area for the drawing.
	No drawing will occur outside this Rect.

	\param colours
	ColourRect object describing the colours to be applied when drawing the
	text.  NB: The colours specified in here are applied to each glyph,
	rather than the text as a whole.

	\param space_extra
	Number of additional pixels of spacing to be added to space characters.

	\param x_scale
	Scaling factor to be applied to each glyph's x axis, where 1.0f is
	considered to be 'normal'.

	\param y_scale
	Scaling factor to be applied to each glyph's y axis, where 1.0f is
	considered to be 'normal'.
	*/
	void drawText(GeometryBuffer& buffer, const String& text,
		const Vector2& position, const hgeRect* clip_rect,
		const ColourRect& colours, const float space_extra = 0.0f,
		const float x_scale = 1.0f, const float y_scale = 1.0f);

	//Notify the Font that the display size may have changed.
	void notifyDisplaySizeChanged(const Size& size);

	//Return the pixel line spacing value for.
	float getLineSpacing(float y_scale = 1.0f) const
	{ return d_height * y_scale; }

	//return the exact pixel height of the font.
	float getFontHeight(float y_scale = 1.0f) const
	{ return (d_ascender - d_descender) * y_scale; }

	//Return the number of pixels from the top of the highest glyph
	//to the baseline
	float getBaseline(float y_scale = 1.0f) const
	{ return d_ascender * y_scale; }


	//Return the pixel width of the specified text if rendered with
	//this Font.
	float getTextExtent(const String& text, float x_scale = 1.0f) const;

	//Return the index of the closest text character in String \a text
	//that corresponds to pixel location \a pixel if the text were rendered.
	size_t getCharAtPixel(const String& text, float pixel,
		float x_scale = 1.0f) const
	{ return getCharAtPixel(text, 0, pixel, x_scale); }


	//Return the index of the closest text character in String \a text,
	//starting at character index \a start_char, that corresponds
	//to pixel location \a pixel if the text were to be rendered.
	size_t getCharAtPixel(const String& text, size_t start_char, float pixel,
		float x_scale = 1.0f) const;

	//Sets the default resource group to be used when loading font data
	static void setDefaultResourceGroup(const String& resourceGroup)
	{ d_defaultResourceGroup = resourceGroup; }


	//Returns the default resource group currently set for Fonts.
	static const String& getDefaultResourceGroup()
	{ return d_defaultResourceGroup; }

	//Return a pointer to the glyphDat struct for the given codepoint,
	//or 0 if the codepoint does not have a glyph defined.
	const hgeFontGlyph* getGlyphData(utf32 codepoint) const;

protected:
	//! Definition of CodepointMap type.
	typedef std::map<utf32, hgeFontGlyph> CodepointMap;
	//! Contains mappings from code points to Image objects
	CodepointMap d_cp_map;

	//Copy the current glyph data into a buffer, which has a width of
	//a buf_width pixels (not bytes).
	void drawGlyphToBuffer(argb_t* buffer, UINT buf_width) const;

	//Return the required texture size required to store imagery for the
	UINT getTextureSize(CodepointMap::const_iterator s,	CodepointMap::const_iterator e) const;

	//Free all allocated font data.
	void free();

	void rasterise(utf32 start_codepoint, utf32 end_codepoint) const;

	void updateFont();

	//Set the maximal glyph index. This reserves the respective
	//number of bits in the d_glyphPageLoaded array.
	void setMaxCodepoint(utf32 codepoint);

	//! Name of this font.
	String d_name;

	//! Type name string for this font (not used internally)
	String d_type;

	//! Name of the file used to create this font (font file or imagset)
	String d_filename;

	//! Name of the font file's resource group.
	String d_resourceGroup;

	//! Holds default resource group for font loading.
	static String d_defaultResourceGroup;

	//! maximal font ascender (pixels above the baseline)
	float d_ascender;
	//! maximal font descender (negative pixels below the baseline)
	float d_descender;
	//! (ascender - descender) + linegap
	float d_height;

	//! Maximal codepoint for font glyphs
	utf32 d_maxCodepoint;

	/*!
	\brief
	This bitmap holds information about loaded 'pages' of glyphs.
	A glyph page is a set of 256 codepoints, starting at 256-multiples.
	For example, the 1st glyph page is 0-255, fourth is 1024-1279 etc.
	When a specific glyph is required for painting, the corresponding
	bit is checked to see if the respective page has been rasterised.
	If not, the rasterise() method is invoked, which prepares the
	glyphs from the respective glyph page for being painted.

	This array is big enough to hold at least max_codepoint bits.
	If this member is NULL, all glyphs are considered pre-rasterised.
	*/
	UINT* d_glyphPageLoaded;

	//! Point size of font.
	float d_ptSize;

	//! True if the font should be rendered as anti-alaised by freeType.
	bool d_antiAliased;

	//! FreeType-specific font handle
	FT_Face d_fontFace;

	//! Type definition for ImagesetVector.
	typedef std::vector<Texture*> TextureVector;
	//! Texture that holds the glyphs for this font.
	mutable TextureVector d_glyphImages;
};

#endif	// end of guard _HgeFont_h_
